
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

package com.hlkj.pay.app.common.impl;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.extension.executor.ExtensionExecutor;
import com.hlkj.framework.extension.scenario.BizScenario;
import com.hlkj.framework.http.template.OkHttpTemplate;
import com.hlkj.pay.app.common.ICommonAppService;
import com.hlkj.pay.app.common.IUploadService;
import com.hlkj.pay.app.common.OcrExtPt;
import com.hlkj.pay.common.CommonResultCode;
import com.hlkj.pay.common.constants.MerchantConstant;
import com.hlkj.pay.dto.Base64Dto;
import com.hlkj.pay.dto.GaoDeGeoDto;
import com.hlkj.pay.dto.common.GeetestConfig;
import com.hlkj.pay.dto.common.LocationDto;
import com.hlkj.pay.dto.common.OcrConfig;
import com.hlkj.pay.dto.common.StorageConfig;
import com.hlkj.pay.dto.common.ocr.OcrScan;
import com.hlkj.pay.dto.common.ocr.OcrScanResult;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.infrastructure.model.common.PlatFormConfigDO;
import com.hlkj.pay.infrastructure.model.common.TemplateDO;
import com.hlkj.pay.service.common.IBusinessLogService;
import com.hlkj.pay.service.common.IPlatFormConfigService;
import com.hlkj.pay.service.common.ITemplateService;
import com.hlkj.pay.util.ImageUtils;
import com.hlkj.pay.vo.common.req.EmailSendReq;
import com.hlkj.pay.vo.common.req.SmsSendReq;
import com.hlkj.pay.vo.common.req.TestSendReq;
import com.hlkj.pay.vo.common.req.WechatSendReq;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.IoUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author monk@techsun.com
 * @date 2023/04/25 14:31
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CommonAppServiceImpl implements ICommonAppService {

    private final MessageSendCommonService messageSendCommonService;

    private final IPlatFormConfigService platFormConfigService;

    private final ITemplateService templateService;

    private final ExtensionExecutor extensionExecutor;

    private final IBusinessLogService businessLogService;

    private final OkHttpTemplate okHttpTemplate;

    private final IUploadService uploadService;

    @Override
    public CommonResult<String> sendTest(TestSendReq testSendReq) {
        TemplateDO detail = templateService.detail(testSendReq.getTemplateCode());
        if (detail == null) {
            return CommonResult.error(CommonResultCode.TEMPLATE_DOES_NOT_EXIST);
        }
        if (CollectionUtils.isEmpty(testSendReq.getReceiverList())) {
            return CommonResult.error(CommonResultCode.PARAMETER_MISSING);
        }
        // List<BatchSendConsumer> batchSendConsumers = new ArrayList<>();
        // testSendReq.getReceiverList().stream().forEach(receiver -> {
        // batchSendConsumers.add(BatchSendConsumer.builder().receiver(messageConsumerSelector.testReceiver(receiver)).build());
        // });
        // List<TemplateVariableDO> templateVariableList =
        // templateVariableService.queryList();
        // MessageSendParamsReq messageSendParamsReq = new MessageSendParamsReq();
        // Map<String, Object> fieldMap = BeanUtil.beanToMap(messageSendParamsReq);
        //
        // templateVariableList.stream().forEach(templateVariableDO -> {
        // if (fieldMap.containsKey(templateVariableDO.getFieldName())) {
        // fieldMap.put(templateVariableDO.getFieldName(),
        // templateVariableDO.getPreviewValue());
        // }
        // });
        // String jsonString = JsonUtils.toJsonString(fieldMap);
        // messageSendParamsReq = JsonUtils.parseObject(jsonString,
        // MessageSendParamsReq.class);
        // List<TemplateParamReq> templateParamReqs =
        // TemplateVariableUtils.templateParamList(detail.getLanguageTemplate().getContent(),
        // templateVariableList);
        // messageSendCommonService.processBatchSend(templateParamReqs,
        // batchSendConsumers, messageSendParamsReq, detail, Boolean.TRUE);
        return CommonResult.success();
    }

    @Override
    public CommonResult<String> sendSms(SmsSendReq smsSendReq) {
        log.info("sendSms smsSendReq:{}", JsonUtils.toJsonString(smsSendReq));
        try {
            TemplateDO detail = templateService.detail(smsSendReq.getTemplateCode());
            if (detail == null) {
                return CommonResult.error(CommonResultCode.TEMPLATE_DOES_NOT_EXIST);
            }
            CommonEnum.TEMPLATE_TYPE templateType = CommonEnum.TEMPLATE_TYPE.from(detail.getTemplateType());
            CommonResult<String> commonResult;
            switch (templateType) {
                case INTERNATIONAL_SMS:
                case DOMESTIC_SMS:
                    commonResult = messageSendCommonService.sendSms(detail, smsSendReq);
                    break;
                default:
                    commonResult = CommonResult.error(CommonResultCode.TEMPLATE_DOES_NOT_EXIST);
            }
            if (!commonResult.isSuccess()) {
                // messageSendCommonService.addSmsLog(smsSendReq,
                // CommonEnum.LOG_TYPE.EXCEPTION_LOG, commonResult.getMsg());
            }
            return commonResult;
        }
        catch (Exception e) {
            log.error("sendSms error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<String> sendEmail(EmailSendReq emailSendReq) {
        try {
            TemplateDO detail = templateService.detail(emailSendReq.getTemplateCode());
            if (detail == null) {
                return CommonResult.error(CommonResultCode.TEMPLATE_DOES_NOT_EXIST);
            }
            CommonResult<String> commonResult = messageSendCommonService.sendEmail(detail, emailSendReq);
            if (!commonResult.isSuccess()) {
                // messageSendCommonService.addEmailLog(emailSendReq,
                // CommonEnum.LOG_TYPE.EXCEPTION_LOG, commonResult.getMsg());
            }
            return commonResult;

        }
        catch (Exception e) {
            log.error("sendEmail error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }

    @Override
    public CommonResult<String> sendWechat(WechatSendReq wechatSendReq) {
        return null;
    }

    @Override
    public CommonResult<OcrScanResult> ocrScan(OcrScan ocrScan) {
        OcrConfig ocrConfig = platFormConfigService.getOcrConfig();
        ocrScan.setOcrConfig(ocrConfig);
        return extensionExecutor.execute(OcrExtPt.class, BizScenario.valueOf(ocrConfig.getType(), ocrScan.getType()), ex -> ex.ocrScan(ocrScan));
    }

    @Override
    public Map<String, Object> sysConfig() {
        // 平台配置加 极验id+oss
        List<PlatFormConfigDO> platFormConfigList = platFormConfigService.platFormConfigList(CommonEnum.CONFIG_TYPE.APP_INFO.getType());
        if (CollectionUtils.isEmpty(platFormConfigList)) {
            return Collections.emptyMap();
        }
        Map<String, Object> config = new HashMap<>();
        platFormConfigList.stream().forEach(platFormConfig -> {
            CommonEnum.CONFIG_TYPE configType = CommonEnum.CONFIG_TYPE.from(platFormConfig.getConfigName());
            if (configType != null) {
                config.put(platFormConfig.getConfigName(), JsonUtils.parseObject(platFormConfig.getConfigValue(), configType.getClassName()));
            }
        });
        GeetestConfig geetestConfig = platFormConfigService.getGeetestConfig();
        if (geetestConfig != null) {
            config.put("geetestId", geetestConfig.getGeetestId());
        }
        StorageConfig storageConfig = platFormConfigService.getStorageConfig();
        if (storageConfig != null) {
            config.put("ossDomain", storageConfig.getDomain());
        }
        return config;
    }

    @Override
    public void saveOrUpdateConfig(PlatFormConfigDO platFormConfigDO) {
        PlatFormConfigDO configDO = platFormConfigService.platFormConfigByName(platFormConfigDO.getConfigName());
        if (configDO == null) {
            platFormConfigService.savePlatFormConfig(platFormConfigDO);
        }
        else {
            platFormConfigDO.setId(configDO.getId());
            platFormConfigService.updatePlatFormConfig(platFormConfigDO, configDO.getType());
            // 变更日志
            businessChangeLog(configDO, platFormConfigDO);
        }
    }

    @Override
    public CommonResult<String> urlToBase64(String imageUrl) {
        try {
            String imageType = ImageUtils.getImageTypeFromUrl(imageUrl);
            if (StringUtils.isEmpty(imageType)) {
                return CommonResult.error(CommonResultCode.FILE_ERROR);
            }
            URL url = new URL(imageUrl);
            InputStream inputStream = url.openStream();
            // 将图片转换为 Base64 编码的字符串
            byte[] imageBytes = IoUtil.readBytes(inputStream);
            String base64String = Base64.encode(imageBytes);
            // 输出 Base64 字符串
            IoUtil.close(inputStream);
            return CommonResult.success(base64String);
        }
        catch (IOException e) {
            log.error("sendEmail error:{}", e.getMessage(), e);
            return CommonResult.error(CommonResultCode.SERVICE_ERROR);
        }
    }
    @Override
    public CommonResult<String> base64ToUrl(Base64Dto base64) {
        // byte[] imageBytes = Base64.decode(base64.getBase64());
        // byte[] imageBytes = java.util.Base64.getDecoder().decode(qr_code);
        byte[] imageBytes=java.util.Base64.getDecoder().decode(base64.getBase64().replace("data:image/png;base64,",""));
        return uploadService.upload(imageBytes, CommonEnum.OssEnum.IMAGE);
    }

    @Override
    public CommonResult<String> qrCode(String url) {
        byte[] qrCodeBytes = QrCodeUtil.generatePng(url, 300, 300);
        return uploadService.upload(qrCodeBytes, CommonEnum.OssEnum.IMAGE);
    }

    @Override
    public CommonResult<LocationDto> location(String address) {
        String string = okHttpTemplate.get(MerchantConstant.GAODE_GEO_URL + address, null);
        GaoDeGeoDto gaoDeGeoDto = JsonUtils.parseObject(string, GaoDeGeoDto.class);
        List<GaoDeGeoDto.GeocodesBean> geocodes = gaoDeGeoDto.getGeocodes();
        if (CollectionUtils.isEmpty(geocodes)) {
            return CommonResult.success();
        }
        String location = geocodes.get(0).getLocation();
        if (StringUtils.isEmpty(location)) {
            return CommonResult.success();
        }
        String[] split = location.split(",");
        LocationDto locationDto = new LocationDto();
        locationDto.setLongitude(split[1]);
        locationDto.setLatitude(split[0]);
        return CommonResult.success();
    }



    /**
     * log object
     * 
     * @param beforePayChannel
     * @param afterPayChannel
     * @return
     */
    void businessChangeLog(PlatFormConfigDO beforePayChannel, PlatFormConfigDO afterPayChannel) {
        CommonEnum.CONFIG_TYPE configType = CommonEnum.CONFIG_TYPE.from(beforePayChannel.getConfigName());
        businessLogService.addBusinessChangeLog(beforePayChannel.getConfigName(), configType.getChangeLogType().getCode(), CommonEnum.CHANGE_LOG_MODEL_TYPE.COMMON,
                beforePayChannel, afterPayChannel);
    }
}
